import ValuePair from "../dictionary/valuePair";
import Dictionary from "../dictionary";
import Node from "../linkedList/node";

export type Coord = [number, number];

/**
 * #### 数据结构基础接口
 */
interface Structure {
  /**
   * 判断数据结构是否为空
   */
  isEmpty(): boolean;

  /**
   * 数据结构元素长度
   */
  size(): number;

  /**
   * 清除数据结构元素
   */
  clear(): void;

  /**
   * #### 返回数据结构字符串表示
   */
  toString(): string | null;
}

/**
 * #### 栈接口
 */
export interface IStack<T> extends Structure {
  /**
   * 移除栈顶元素并返回该元素
   */
  pop(): T | undefined;

  /**
   * #### 向栈顶添加元素
   * @param item 要添加的元素
   */
  push(...args: Array<T>): void;

  /**
   * #### 返回栈顶元素，但不移除
   */
  peek(): T | undefined;
}

/**
 * #### 对象栈接口
 */
export interface ObjStack<T> {
  [propName: number]: T;
}

/**
 * #### 队列接口
 */
export interface IQueue<T> extends Structure {
  /**
   * 移除队列第一个元素并返回该元素
   */
  dequeue(): T | undefined;

  /**
   * #### 向队列末尾添加元素
   * @param item 要添加的元素
   */
  enqueue(...args: Array<T>): void;

  /**
   * #### 返回队列第一个元素，但不移除
   */
  front(): T | undefined;
}

/**
 * #### 堆接口
 */
export interface Heap<T> extends Structure {
  /**
   * #### 插入一个值，返回一个布尔值
   * @param value 要插入的值
   */
  insert(value: T): boolean;

  /**
   * #### 移除最小值或最大值，返回该值
   */
  extract(): T | undefined;

  /**
   * 查找一个值
   * @param value 要查找的值
   */
  find(): T | undefined;
}

/**
 * #### 字典接口
 */
export interface IDictionary<K, V> extends Structure {
  /**
   * #### 键值对数组
   */
  table: Array<ValuePair<K, V>>;

  /**
   * #### 设置键值对
   * @param key 键
   * @param value 值
   */
  set(key: K, value: V): void;

  /**
   * #### 删除键值对
   * @param key 键
   */
  remove(key: K): ValuePair<K, V> | undefined;

  /**
   * #### 判断键是否存在
   * @param key 键
   */
  has(key: K): boolean;

  /**
   * #### 获取键值对
   * @param key 键
   */
  get(key: K): ValuePair<K, V> | undefined;

  /**
   * #### 获取键数组
   */
  keys(): Array<K>;

  /**
   * #### 获取值数组
   */
  values(): Array<V>;

  /**
   * #### 获取键值对数组
   */
  keyValues(): Array<[K, V]>;

  /**
   * 遍历键值对
   * @param callbackFunc 回调函数
   */
  forEach(callbackFunc: (key: K, value: V) => boolean | void): void;
}

/**
 * #### 图接口
 */
export interface IGraph<T> {
  /**
   * #### 是否是有向图
   */
  isDirected: boolean;
  /**
   * #### 图中的顶点集合
   */
  vertices: Array<T>;
  /**
   * #### 邻接表，用于表示顶点之间的连接关系
   */
  adjList: Dictionary<T, Array<T>>;
  /**
   * #### 添加顶点的方法
   * @param v 顶点
   */
  addVertex(v: T): void;
  /**
   * #### 添加边的方法
   * @param v 顶点
   * @param w
   */
  addEdge(v: T, w: T): void;
  /**
   * #### 获取顶点集合的方法
   */
  getVertices(): Array<T>;
  /**
   * #### 获取邻接表的方法
   */
  getAdjacencyList(): Dictionary<T, Array<T>>;
}

/**
 * #### 链表接口
 */
export interface ILinkedList<T> extends Structure {
  /**
   * #### 向链表中添加元素
   * @param element 要添加的元素
   */
  push(element: T): void;

  /**
   * #### 在指定位置插入元素
   * @param element 要插入的元素
   * @param index 插入的位置索引
   */
  insert(element: T, index: number): void;

  /**
   * #### 获取指定位置的节点
   * @param index 指定位置索引
   */
  getElementAt(index: number): Node<T> | undefined;

  /**
   * #### 获取指定位置的值
   * @param index 指定位置索引
   */
  getValueAt(index: number): T | undefined;

  /**
   * #### 移除指定位置的元素
   * @param index 指定位置索引
   */
  removeAt(index: number): T | undefined;

  /**
   * #### 移除指定元素
   * @param element 指定元素
   */
  remove(element: T): T | undefined;

  /**
   * #### 获取指定元素的索引
   * @param element 指定元素
   */
  indexOf(element: T): number | undefined;
}

/**
 * #### 双端链表节点接口
 */
export interface LinkLineNode<T> {
  /**
   * #### 前一个节点
   */
  pre: LinkLineNode<T> | null;
  /**
   * #### 后一个节点
   */
  next: LinkLineNode<T> | null;
  /**
   * #### 节点值
   */
  value: T | null;
  /**
   * #### 节点键
   */
  key: string;
}

/**
 * #### 双端链表接口
 */
export interface LinkLine<T> {
  /**
   * #### 将头部第一个节点删除，成功则返回删除的节点值
   */
  shift(): T | undefined;
  /**
   * #### 在头部插入一个节点，成功则返回当前链表的长度
   * @param args 要添加的元素
   */
  unshift(...args: Array<T>): void;
  /**
   * #### 将尾部第一个节点删除，成功则返回删除的节点值
   */
  pop(): T | undefined;
  /**
   * #### 在尾部插入一个节点，成功则返回当前链表的长度
   * @param args 要添加的元素
   */
  push(...args: Array<T>): void;
  /**
   * #### 根据键查找节点
   * @param key 要查找的键
   */
  delete(key: string): LinkLineNode<T> | undefined;
  /**
   * #### 将链表节点值按顺序存放数组返回
   */
  getValList(): Array<T>;
  /**
   * #### 根据键查找节点
   * @param key 要查找的键
   */
  get(key: string): LinkLineNode<T> | undefined;
}
